﻿using IOA.MES.Common;
using IOA.MES.WebTool.Common;
using IOA.MES.WebTool.WebSocketSupport.CommandModels;
using Newtonsoft.Json;
using NLog;
using OfficeOpenXml;
using Seagull.BarTender.Print;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;


namespace IOA.MES.WebTool.WebSocketSupport
{
    public class MesToolMsgHandler
    {
        public MesToolSession Session { get; set; }

        /// <summary>
        /// 登录/心跳
        /// </summary>
        public void Login(LoginModel message)
        {
            Session.Token = message.Token;
        }

        /// <summary>
        /// 打印条码
        /// </summary>
        public void PrintCodes(PrintModel message)
        {
            try
            {
                var resposne = BaseEnv.InvokeApi<GetPrintTaskResponse>("/api/WebTool/GetPrintTask", Session.Token, new { TaskId = message.TaskId });
                if (resposne.ErrCode != 200)
                {
                    CommonMessage.Alert(resposne.ErrMsg);
                    return;
                }
                else if (resposne.Data.PrintItems == null || !resposne.Data.PrintItems.Any())
                {
                    CommonMessage.Alert("未找到待打印的条码\r\nNo barcode to be printed found");
                    return;
                }

                var labelPath = $"{BaseEnv.LocalDirectory}\\data";
                if (!Directory.Exists(labelPath))
                {
                    Directory.CreateDirectory(labelPath);
                }
                var fileName = resposne.Data.Label.Substring(resposne.Data.Label.LastIndexOf("/") + 1);
                var localFileName = $"{labelPath}\\{fileName}";
                if (!File.Exists(localFileName))
                {
                    try
                    {
                        new FtpUtils(BaseEnv.FtpUserName, BaseEnv.FtpPassword).Download(resposne.Data.Label, localFileName);
                    }
                    catch (Exception ex)
                    {
                        CommonMessage.Alert($"【{message.TaskId}】下载标签文件错误：{resposne.Data.Label}\r\n{ex.Message}");
                        return;
                    }
                }

                ExcuteSql("delete from 条码");
                foreach (var item in resposne.Data.PrintItems)
                {
                    ExcuteSql($"INSERT INTO 条码 (条码) VALUES ('{item.BarCode}')");
                    ExcuteSql($"INSERT INTO 条码 (条码) VALUES ('{item.BarCode}')");
                }

                var engine = new Engine(true);
                lock (engine)
                {
                    var format = engine.Documents.Open(localFileName);
                    if (format.PrintSetup.SupportsIdenticalCopies)
                    {
                        format.PrintSetup.IdenticalCopiesOfLabel = 1;
                    }

                    format.PrintSetup.PrinterName = BaseEnv.LabelPrinter;
                    int waitForCompletionTimeout = 10000;// 10秒
                    Messages messages;
                    Result result = format.Print($"PrintCodes_{message.TaskId}", waitForCompletionTimeout, out messages);
                    string messageString = "\n\nMessages:";
                    foreach (Message msg in messages)
                    {
                        messageString += "\n\n" + msg.Text;
                    }
                    CommonMessage.Log(LogLevel.Info, messageString);
                }
            }
            catch (PrintEngineException ex)
            {
                CommonMessage.Alert(ex.Message);
            }
            catch (Exception ex)
            {
                CommonMessage.Alert($"【{message.TaskId}】打印条码出现未知异常\r\nUnknown exception while printing barcode\r\n{ex.ToString()}");
            }
        }

        private void ExcuteSql(string sql)
        {
            string strConn = $@" Provider=Microsoft.Jet.OLEDB.4.0;Data Source={BaseEnv.LocalDirectory}\\data\\data.mdb";
            var myConn = new OleDbConnection(strConn);
            myConn.Open();
            var inst = new OleDbCommand(sql, myConn);
            inst.ExecuteNonQuery();
            myConn.Close();
        }
        private DataTable GetLastData(string sql)
        {
            try
            {
                var conn = new OleDbConnection($"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={BaseEnv.LocalDirectory}\\data\\data.mdb");
                conn.Open();
                var cmd = conn.CreateCommand();
                cmd.CommandText = sql;
                var dr = cmd.ExecuteReader();
                System.Data.DataTable dt = new System.Data.DataTable();
                if (dr.HasRows)
                {
                    for (int i = 0; i < dr.FieldCount; i++)
                    {
                        dt.Columns.Add(dr.GetName(i));
                    }
                    dt.Rows.Clear();
                }
                while (dr.Read())
                {
                    DataRow row = dt.NewRow();
                    for (int i = 0; i < dr.FieldCount; i++)
                    {
                        row[i] = dr[i];
                    }
                    dt.Rows.Add(row);
                }
                cmd.Dispose();
                conn.Close();

                return dt;
            }
            catch (Exception ex)
            {
                CommonMessage.Alert($"读取Access出错：{ex.ToString()}", false);
                return null;
            }
        }

        /// <summary>
        /// 打印唛头和边框条码
        /// </summary>
        public void PrintPack(PrintPackModel message)
        {
            GetPackMarkResponse responseData = null;
            try
            {
                var resposne = BaseEnv.InvokeApi<GetPackMarkResponse>("/api/WebTool/GetPackMark", Session.Token, new { PackNo = message.PackNo });
                if (resposne.ErrCode != 200)
                {
                    CommonMessage.Alert(resposne.ErrMsg);
                    return;
                }
                responseData = resposne.Data;
                CommonMessage.Log(LogLevel.Info, $"打包编号：{resposne.Data.PackInfo.PackNo}，组件数：{resposne.Data.Products.Count}，报文：{JsonConvert.SerializeObject(resposne)}");
            }
            catch (Exception ex)
            {
                CommonMessage.Alert($"【{message.PackNo}】获取打包标签出现未知错误\r\nUnknown error while getting packaging label\r\n{ex.Message}", true, ex);
                return;
            }

            if (message.PrintType == 0 || message.PrintType == 2)
            {
                try
                {
                    var templatePath = $"{BaseEnv.LocalDirectory}\\data\\packmark\\templates\\";
                    var printPath = $"{BaseEnv.LocalDirectory}\\data\\packmark\\print\\{DateTime.Today.ToString("yyyyMMdd")}\\";
                    if (!Directory.Exists(templatePath))
                    {
                        Directory.CreateDirectory(templatePath);
                    }
                    if (!Directory.Exists(printPath))
                    {
                        Directory.CreateDirectory(printPath);
                    }
                    var fileName = responseData.PackMark.Substring(responseData.PackMark.LastIndexOf("/") + 1);
                    var localFileName = $"{templatePath}{fileName}";
                    if (!File.Exists(localFileName))
                    {
                        try
                        {
                            new FtpUtils(BaseEnv.FtpUserName, BaseEnv.FtpPassword).Download(responseData.PackMark, localFileName);
                        }
                        catch (Exception ex)
                        {
                            CommonMessage.Alert($"【{message.PackNo}】下载唛头文件错误\r\n Error downloading shipping mark file：{responseData.PackMark}\r\n{ex.Message}", true, ex);
                            return;
                        }
                    }

                    var printFile = $"{printPath}{message.PackNo}_{DateTime.Now:HHmmss}_{fileName}";
                    File.Copy(localFileName, printFile);

                    WriteMarkExcel(printFile, responseData);
                    CommonMessage.Log(LogLevel.Info, $"唛头生成完成\r\nMark generation completed：{printFile}");

                    System.Diagnostics.Process.Start(printFile);
                }
                catch (Exception ex)
                {
                    CommonMessage.Alert($"【{message.PackNo}】生成唛头文件错误\r\nError in generating shipping mark file\r\n{ex.Message}", true, ex);
                }
            }

            if (message.PrintType == 1 || message.PrintType == 2)
            {
                try
                {
                    if (string.IsNullOrWhiteSpace(responseData.BorderBarCode))
                    {
                        CommonMessage.Alert($"【{message.PackNo}】当前工单边框条码模板未上传\r\nThe frame barcode template for current workorder  has not been uploaded");
                        return;
                    }
                    else if (string.IsNullOrWhiteSpace(BaseEnv.LabelPrinter))
                    {
                        CommonMessage.Alert($"请配置标签打印机，否则无法打印边框条码\r\n Please configure the label printer, otherwise the border barcode cannot be printed");
                        return;
                    }

                    var labelPath = $"{BaseEnv.LocalDirectory}\\data";
                    if (!Directory.Exists(labelPath))
                    {
                        Directory.CreateDirectory(labelPath);
                    }

                    var fileName = responseData.BorderBarCode.Substring(responseData.BorderBarCode.LastIndexOf("/") + 1);
                    var localFileName = $"{labelPath}\\{fileName}";
                    if (!File.Exists(localFileName))
                    {
                        try
                        {
                            new FtpUtils(BaseEnv.FtpUserName, BaseEnv.FtpPassword).Download(responseData.BorderBarCode, localFileName);
                        }
                        catch (Exception ex)
                        {
                            CommonMessage.Alert($"【{message.PackNo}】下载标签文件错误：{responseData.BorderBarCode}\r\n{ex.Message}", true, ex);
                            return;
                        }
                    }

                    ExcuteSql("delete from 条码");
                    foreach (var item in responseData.Products)
                    {
                        ExcuteSql($"INSERT INTO 条码 (条码) VALUES ('{item.BarCode}')");
                    }

                    var engine = new Engine(true);
                    lock (engine)
                    {
                        var format = engine.Documents.Open(localFileName);
                        if (format.PrintSetup.SupportsIdenticalCopies)
                        {
                            format.PrintSetup.IdenticalCopiesOfLabel = 1;
                        }

                        format.PrintSetup.PrinterName = BaseEnv.LabelPrinter;
                        int waitForCompletionTimeout = 10000;// 10秒
                        Messages messages;
                        Result result = format.Print($"PrintCodes_{message.PackNo}", waitForCompletionTimeout, out messages);
                        string messageString = "\n\nMessages:";
                        foreach (Message msg in messages)
                        {
                            messageString += "\n\n" + msg.Text;
                        }
                        CommonMessage.Log(LogLevel.Info, messageString);
                    }
                }
                catch (PrintEngineException ex)
                {
                    CommonMessage.Alert(ex.Message, true, ex);
                }
                catch (Exception ex)
                {
                    CommonMessage.Alert($"【{message.PackNo}】打印边框条码异常\r\n{ex.ToString()}", true, ex);
                }
            }
        }

        private void WriteMarkExcel(string printFile, GetPackMarkResponse response)
        {
            CommonMessage.Log(LogLevel.Info, $"开始WriteMarkExcel：{printFile}");
            using (var package = new ExcelPackage(new FileInfo(printFile)))
            {
                var sheet = package.Workbook.Worksheets["Sheet1"];
                if (sheet == null)
                {
                    throw new Exception("唛头模板中不存在Sheet1\r\n Sheet1 does not exist in the shipping mark template");
                }
                if (response.PackInfo != null)
                {
                    sheet.SetValue(1, 2, response.PackInfo.PackNo);
                    sheet.SetValue(2, 2, response.PackInfo.OrderNo);
                    sheet.SetValue(3, 2, response.PackInfo.NameplateModel);
                    sheet.SetValue(4, 2, response.PackInfo.CurrentLevel);
                    sheet.SetValue(5, 2, response.PackInfo.Color);
                    sheet.SetValue(6, 2, response.PackInfo.Power);
                    sheet.SetValue(7, 2, response.PackInfo.Cell);
                    sheet.SetValue(8, 2, response.PackInfo.BackPlan);
                    sheet.SetValue(9, 2, response.PackInfo.JunBox);
                    sheet.SetValue(10, 2, response.PackInfo.AluFrame);
                    sheet.SetValue(16, 2, response.PackInfo.Chamfer);
                    sheet.SetValue(17, 2, response.PackInfo.Type);
                    sheet.SetValue(18, 2, response.PackInfo.QLevel);
                    sheet.SetValue(19, 2, response.PackInfo.PackDate);
                }
                CommonMessage.Log(LogLevel.Info, $"PackInfo创建完成：{printFile}");
                for (int i = 0; i < response.Products.Count; i++)
                {
                    CommonMessage.Log(LogLevel.Info, $"开始写response.Products[{i}]");
                    sheet.SetValue(i + 2, 3, response.Products[i].BarCode);
                    sheet.SetValue(i + 2, 4, response.Products[i].Temp);
                    sheet.SetValue(i + 2, 5, response.Products[i].Voc);
                    sheet.SetValue(i + 2, 6, response.Products[i].Isc);
                    sheet.SetValue(i + 2, 7, response.Products[i].Pm);
                    sheet.SetValue(i + 2, 8, response.Products[i].Vm);
                    sheet.SetValue(i + 2, 9, response.Products[i].Im);
                    sheet.SetValue(i + 2, 10, response.Products[i].EFF);
                    sheet.SetValue(i + 2, 11, response.Products[i].FF);
                    sheet.SetValue(i + 2, 12, response.Products[i].Time);
                    sheet.SetValue(i + 2, 13, response.Products[i].Time);
                    sheet.SetValue(i + 2, 14, response.Products[i].VerifyCode);
                }

                package.Save();
            }

            CommonMessage.Log(LogLevel.Info, $"ReleaseComObject完成");
        }

        /// <summary>
        /// 下载图片
        /// </summary>
        public void DownloadImages(DownloadImagesModel message)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(BaseEnv.ImageFolder) || !Directory.Exists(BaseEnv.ImageFolder))
                {
                    MessageBox.Show("请先选择图片下载位置，然后重新下载！\r\n Please select the image download location first, and then download again!");
                    new WinSetting().ShowDialog();
                    return;
                }
                var request = new
                {
                    ByType = message.ByType,
                    Codes = message.Codes.Where(_ => !string.IsNullOrWhiteSpace(_)).Select(_ => _.ToUpper().Trim()).ToList(),
                    SiteTypes = message.SiteTypes.Distinct().ToList()
                };
                var resposne = BaseEnv.InvokeApi<QueryDownloadImagesResponse>("/api/WebTool/QueryDownloadImages", Session.Token, request);
                if (resposne.ErrCode != 200)
                {
                    CommonMessage.Alert(resposne.ErrMsg);
                    return;
                }
                else if (resposne.Data == null || resposne.Data.DownloadItems == null || !resposne.Data.DownloadItems.Any())
                {
                    MessageBox.Show("没有要下载的资源\r\nThere are no resources to download");
                    return;
                }

                var curDirectory = string.Empty;
                if (request.Codes.Count == 1) //下载单个包装的文件
                {
                    curDirectory = $"{BaseEnv.ImageFolder}{request.Codes[0]}";
                    for (int i = 1; i > 0; i++)
                    {
                        if (Directory.Exists(curDirectory))
                        {
                            curDirectory = $"{BaseEnv.ImageFolder}{request.Codes[0]}_{i}";
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                else
                {
                    while (true)
                    {
                        curDirectory = $"{BaseEnv.ImageFolder}{DateTime.Now:yyyyMMddHHmmss}";
                        if (Directory.Exists(curDirectory))
                        {
                            Thread.Sleep(1000);
                            continue;
                        }
                        break;
                    }
                }
                Directory.CreateDirectory(curDirectory);
                System.Diagnostics.Process.Start("explorer.exe", curDirectory);

                DownloadImages(curDirectory, resposne.Data.DownloadItems);
            }
            catch (Exception ex)
            {
                CommonMessage.Log(LogLevel.Fatal, $"下载图片异常\r\nAbnormal picture download：{ex.Message}", ex);
                MessageBox.Show($"下载图片异常\r\nAbnormal picture download:{ex}");
            }
        }

        private void DownloadImages(string curDirectory, List<DownloadItem> downloadItems)
        {
            foreach (var folder in downloadItems.Where(_ => _.IsFolder).ToList())
            {
                var curFolder = $"{curDirectory}\\{folder.ItemName}";
                Directory.CreateDirectory(curFolder);
                DownloadImages(curFolder, folder.Children);
            }
            foreach (var file in downloadItems.Where(_ => !_.IsFolder).ToList())
            {
                try
                {
                    var localFileName = $"{curDirectory}\\{file.ItemName}{file.DownloadUrl.Substring(file.DownloadUrl.LastIndexOf("."))}";
                    new FtpUtils(BaseEnv.FtpUserName, BaseEnv.FtpPassword).Download(file.DownloadUrl, localFileName);
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"文件下载失败，文件名：{file.ItemName}，下载地址：{file.DownloadUrl}，异常信息：{ex.ToString()}\r\n File download failed, file name：{file.ItemName}，Download path：{file.DownloadUrl}，Error Information：{ex.ToString()}");
                }
            }
        }
    }
}
